package com.icat.house.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.jfinal.ext.kit.ModelExt;
import com.jfinal.ext.plugin.sqlinxml.SqlKit;
import com.jfinal.ext.plugin.tablebind.TableBind;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.ehcache.CacheKit;

/**
 * 基础类
 * 
 * @description
 * @author lixinlin
 * @date 2017年10月26日 下午5:22:38
 *
 */
public class BaseModel<M extends BaseModel<M>> extends ModelExt<M> {

	private static final long serialVersionUID = -5318759252720099782L;

	public static final String COLUMN_ID = "id";
	public static final String COLUMN_CREATE_DATE = "create_date";
	public static final String COLUMN_UPDATE_DATE = "update_date";

	public int getId() {
		Integer id = this.getInt(COLUMN_ID);
		id = id != null ? id.intValue() : 0;
		return id;
	}

	public Date getCreateDate() {
		return this.getDate(COLUMN_CREATE_DATE);
	}

	public Date getUpdateDate() {
		return this.getDate(COLUMN_UPDATE_DATE);
	}

	/***
	 * 用来当 缓存名字 也用来 生成 简单sql
	 */

	public String tableName;

	/***
	 * 反射获取 注解获得 tablename
	 */
	public BaseModel() {
		if (tableName == null) {
			TableBind table = this.getClass().getAnnotation(TableBind.class);
			if (table != null)
				tableName = table.tableName();
		}

	}

	/**
	 * 删除自己的同时 删除 所有 子节点 属性名
	 * 
	 * @param id
	 * @param fieldName
	 * @return
	 */
	public boolean deleteByIdAndfieldName(Integer id, String model, String fieldName) {
		boolean result = deleteById(id);
		Db.update("delete from " + model + " where " + fieldName + "=? ", id);
		return result;
	}

	/**
	 * 根据id更新单个字段
	 * 
	 * @param key
	 * @param value
	 * @param id
	 * @return
	 */
	public boolean update(String key, Object value, Object id) {
		return Db.update("update " + tableName + " set " + key + "=? where id =?", value, id) > 0;
	}

	/***
	 * if empty remove the attr
	 * 
	 * @param attr
	 */
	public BaseModel<M> emptyRemove(String attr) {
		if (get(attr) == null)
			remove(attr);

		return this;
	}

	public BaseModel<M> emptyZreo(String attr) {
		if (get(attr) == null)
			set(attr, 0);
		return this;
	}

	/***
	 * 删除自己的同时 删除 所有 子节点 属性名 必需为pid
	 *
	 * @param id
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public boolean deleteByIdAndPid(Integer id) {
		boolean result = deleteById(id);

		List<BaseModel> list = (List<BaseModel>) list("where pid=?", id);

		for (BaseModel m : list) {
			deleteByIdAndPid(Integer.valueOf(m.get("id") + ""));

			Db.update("delete from " + tableName + " where pid=? ", id);
		}

		return result;
	}

	/***
	 * 禁用自己的同时 禁用 所有 子节点 属性名 必需为pid
	 *
	 * @param id
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public boolean forbidByIdAndPid(Integer id) {
		boolean result = findById(id).set("status", 0).update();

		List<BaseModel> list = (List<BaseModel>) list("where pid=?", id);

		for (BaseModel m : list) {
			forbidByIdAndPid(Integer.valueOf(m.get("id") + ""));

			Db.update("update " + tableName + " set status=0 where pid=? ", id);
		}

		return result;
	}

	/***
	 * 启用自己的同时启用 所有 子节点 属性名 必需为pid
	 *
	 * @param id
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public boolean resumeByIdAndPid(Integer id) {
		boolean result = findById(id).set("status", 1).update();

		List<BaseModel> list = (List<BaseModel>) list("where pid=?", id);

		for (BaseModel m : list) {
			resumeByIdAndPid(Integer.valueOf(m.get("id") + ""));

			Db.update("update " + tableName + " set status=1 where pid=? ", id);
		}

		return result;
	}

	/***
	 * ids 必需为 连续的 1，2，3 这样子
	 * 
	 * @param ids
	 */
	public boolean batchDelete(String ids) {
		if (StrKit.isBlank(ids))
			return false;
		return Db.update("delete from " + tableName + " where id in (" + ids + ")") > 0;

	}

	/***
	 * 删除多条记录，并删除子节点 属性名 必需为pid
	 * 
	 * @param ids
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public boolean multidelDelete(String ids) {
		if (StrKit.isBlank(ids))
			return false;
		boolean result = false;
		String id[] = ids.split(",");
		for (int i = 0; i < id.length; i++) {
			result = deleteById(id[i]);
			List<BaseModel> list = (List<BaseModel>) list("where pid=?", id[i]);

			for (BaseModel m : list) {
				Db.update("delete from " + tableName + " where pid=? ", Integer.valueOf(m.get("id") + ""));
			}
		}
		return result;

	}

	/**
	 * 根据 id 判断的
	 */
	public void saveOrUpdate() {
		if (getInt("id") != null)
			update();
		else
			save();
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public boolean pidIsChild(Integer id, Integer pid) {
		boolean result = false;
		if (pid != null) {
			List<BaseModel> list = (List<BaseModel>) list(" where  pid =?  ", id);

			if (list.size() == 0)
				result = false;

			for (BaseModel r : list) {
				if (pid.equals(r.getInt("id"))) {
					result = true;
					return result;
				} else {

					if (pidIsChild(r.getInt("id"), pid)) {
						result = true;
						return result;
					}
				}

			}
		}

		return result;

	}

	public boolean isFind(String sql) {

		return find(sql).size() > 0;
	}

	public M findFirstByWhere(String where, Object... params) {
		List<M> list = list(where, params);
		if (list.size() > 0)
			return list.get(0);
		else
			return null;
	}

	public boolean isFindByWhere(String where, Object... params) {

		return list(where, params).size() > 0;
	}

	/***
	 * 返回全部的数据 比较方便 但不灵活
	 * 
	 * @return
	 */
	public List<M> list() {

		return find(" select *from " + tableName);
	}

	public List<M> listOrderBySequence() {

		return list(" order by sequence");
	}

	public List<M> listOrderBySequence(String where, Object... params) {

		return list(where + " order by sequence", params);
	}

	/***
	 * 返回全部的数据 比较方便 但不灵活
	 * 
	 * @return
	 */
	public List<M> list(String where) {

		return find(" select *from " + tableName + " " + where);
	}

	public List<M> listByCache() {
		return findByCache(" select *from " + tableName);
	}

	public List<M> listByCache(String key, String where, Object... params) {
		return findByCache(key, " select *from " + tableName + " " + where, params);
	}

	public List<M> listByCache(String where) {
		return findByCache(" select *from " + tableName + " " + where);
	}

	/***
	 * 
	 * @return
	 */
	public List<M> list(String where, Object... params) {

		return find(" select *from " + tableName + " " + where, params);
	}

	/***
	 * 返回全部的数据 比较方便 但不灵活
	 * 
	 * @return
	 */
	public List<M> list(int limit) {

		return find(" select *from " + tableName + " limit " + limit);
	}

	public List<M> listOrderLimit(int limit, String order) {

		return find(" select *from " + tableName + " order by " + order + " limit " + limit);
	}

	/***
	 * 返回全部的数据 比较方便 但不灵活
	 * 
	 * @return
	 */
	public List<M> list(int page, int size) {

		if (page < 1)
			page = 0;
		return find(" select *from " + tableName + " limit " + (page - 1) * size + "," + size);
	}

	public M findByIdCache(Object id) {
		String sql = "select * from " + tableName + " where id =" + id;
		M m = CacheKit.get(tableName, sql);
		if (m == null) {
			m = super.findById(id);
			CacheKit.put(tableName, sql, m);
		}

		return m;
	}

	/**
	 * 自动以sql 作为 key
	 * 
	 * @param sql
	 * @return
	 */
	public List<M> findByCache(String sql) {

		return super.findByCache(tableName, sql, sql);
	}

	public List<M> findByCache(String key, String sql, Object... params) {
		return super.findByCache(tableName, key, sql, params);
	}

	public M findFirstByCache(String key, String sql, Object... params) {
		List<M> list = super.findByCache(tableName, key, sql, params);
		if (list.size() > 0)
			return list.get(0);
		else
			return null;
	}

	public Map<String, Object> getAttrs() {
		return super.getAttrs();
	}

	/***
	 * 把 model 转化为 list 找到其中的单个属性
	 * 
	 * @param sql
	 * @param attr
	 * @return
	 */
	public List<String> getAttr(String sql, String attr) {

		List<String> list = new ArrayList<String>();

		for (M t : find(sql)) {

			list.add(t.getStr(attr));
		}
		return list;

	}

	/***
	 * 把 model 转化为 list 找到其中的单个属性
	 * 
	 * @param sql
	 * @param param
	 * @return
	 */
	public List<String> getAttr(String sql, String attr, Object... params) {

		List<String> list = new ArrayList<String>();

		for (M t : find(sql, params)) {

			list.add(t.getStr(attr));
		}
		return list;

	}

	public long getAllCount() {

		return findFirst(" select count(*) as c from " + tableName).getLong("c");
	}

	public long getCountByWhere(String where) {
		return findFirst(" select count(*) as c from " + where).getLong("c");
	}

	public long getCountByWhere(String where, Object... params) {
		return findFirst(" select count(*) as c from " + tableName + " " + where, params).getLong("c");
	}

	public static String sql(String key) {

		return SqlKit.sql(key);
	}

}
